'''
Created on Apr 6, 2011

@author: glow
'''

# Python imports
import binascii
import datetime
import email  # see incoming_mail()
import email.utils
import logging
import md5
import os
import random
import re
import urllib
from cStringIO import StringIO
from xml.etree import ElementTree

# AppEngine imports
from google.appengine.api import mail
from google.appengine.api import memcache
from google.appengine.api import users
from google.appengine.api import urlfetch
from google.appengine.api import xmpp
from google.appengine.ext import db
from google.appengine.ext.db import djangoforms
from google.appengine.runtime import DeadlineExceededError
from google.appengine.runtime import apiproxy_errors

# Django imports
# TODO(guido): Don't import classes/functions directly.
from django import forms

# Import settings as django_settings to avoid name conflict with settings().
from django.conf import settings as django_settings
from django.http import HttpResponse, HttpResponseRedirect
from django.http import HttpResponseForbidden, HttpResponseNotFound
from django.http import HttpResponseBadRequest
from django.shortcuts import render_to_response
import django.template
from django.template import RequestContext
from django.utils import simplejson
from django.utils.safestring import mark_safe
from django.core.urlresolvers import reverse


# load models
import models
from models import Attribute, Collection

from django.conf import settings

from controlledterminology.models import CodedTerminology

class DynamicForm(forms.Form):    
  """
  Dynamic form that allows the user to change and then verify the data that was parsed
  from: http://djangosnippets.org/snippets/714/
  """
  def setFields(self, kwds):
    """
    Set the fields in the form
    """
    #model = self.Meta.model
    keys = kwds.keys()
    keys.sort()
    for k in keys:
      self.fields[k] = kwds[k]
            
  def setData(self, kwds):
    """
    Set the data to include in the form
    """
    for name,field in self.fields.items():
        self.data[name] = field.widget.value_from_datadict(
                            kwds, self.files, self.add_prefix(name))
    self.is_bound = True
            
  def validate(self, post):
    """
    Validate the contents of the form
    """
    for name, field in self.fields.items():
      value = field.widget.value_from_datadict(post, 
                                               self.files, 
                                               self.add_prefix(name))
      try:
        field.clean(value)
      except forms.ValidationError, e:
        self.errors[name] = e.messages
        

# Define columns(attributes)

class AttributeBaseForm(forms.Form):
  attribute_name = forms.CharField(max_length=100,
                                   widget=forms.TextInput(attrs={'size' : 60}))
  
  class Meta:
    model = models.Attribute

# Define rows(variables)

class VariableBaseForm(forms.Form):
  variable_name = forms.CharField(max_length=100,
                                   widget=forms.TextInput(attrs={'size' : 60}))
  
  class Meta:
    model = models.Variable
    

class HierarchyForm(forms.Form):
  pass

class ItemEntryForm(forms.Form):
  """
  Generic Form for the Instance
  """
  pass

class CollectionAttributeTemplateCreationForm(forms.Form):
  name = forms.TextInput()
  label = forms.TextInput()
  definition = forms.TextInput()
  guidelines = forms.TextInput()
  
  class Meta:
    model = models.CollectionAttributeTemplate

class AttributeCreationForm(forms.Form):
  name = forms.TextInput()
  label = forms.TextInput()
  definition = forms.TextInput()
  guidelines = forms.TextInput()
  # load previous Attributes
  _precedents = db.GqlQuery("SELECT __key__ from Attribute ORDER BY rank ASC")
  # use previous Attributes as the Choices
  dependancy = forms.ChoiceField(choices=_precedents)
  dependancy_type = forms.ChoiceField(choices=())
  # Load the coded terms 
  _codedterms = [x.name for x in CodedTerminology.all()]
  dependancy = forms.ChoiceField(choices=_codedterms)
  

def login_required(func):
  """
  Decorator that redirects to the login page if you're not logged in.
  taken from http://code.google.com/p/rietveld/source/browse/trunk/codereview/views.py
  """

  def login_wrapper(request, *args, **kwds):
    if request.user is None:
      return HttpResponseRedirect(
          users.create_login_url(request.get_full_path().encode('utf-8')))
    return func(request, *args, **kwds)

  return login_wrapper

def admin_required(func):
  """
  Decorator that insists that you're logged in as administratior.
  taken from http://code.google.com/p/rietveld/source/browse/trunk/codereview/views.py
  """

  def admin_wrapper(request, *args, **kwds):
    if request.user is None:
      return HttpResponseRedirect(
          users.create_login_url(request.get_full_path().encode('utf-8')))
    if not request.user_is_admin:
      return HttpResponseForbidden('You must be admin in for this function')
    return func(request, *args, **kwds)

  return admin_wrapper
    
def define_attribute(request):
  name = request.GET.get('NAME')
  if not name:
    return 

def index(request):
  """
  Default
  """
  return render_to_response('entry.html', {})


@admin_required
def admin(request):
  """
  Admin page
  """ 
  return render_to_response('admin.html', {})

@admin_required
def admin_attribute(request):
  """
  Admin page
  """ 
  return render_to_response('admin.html', {})

@admin_required
def admin_variable(request):
  """
  Admin page
  Targets: 
  1. Upload or merge new CT
  2. Add Variables
  3. Add Attributes
  """ 
  return render_to_response('admin.html', {})

@login_required
def view(request, path):
  """
  View an element 
  """
  pass

@login_required
def edit(request, path):
  """
  Edit an element 
  """
  pass

"""
Workflow
1. Admin - load CT
2. Admin - Create Variable Templates
3. Admin - Create Attribute Templates
4. Admin - Define Collections Attributes
5. Admin - Define top level collections
6. Admin - Define top level collection attributes
7. Admin - Add variables 
8. Admin - populate variables
"""


@admin_required
def define(request, entity, identifier):
  """
  Define Attributes or Variables
  """
  if request.GET:
    if entity == 'attribute':
      entity_real = models.Attribute(identifier)
      pass
    elif entity == 'variable':
      entity_real = models.Variable(identifier)
      pass
    else:
      return render_to_response('index.html', {'message' : 'No such entity'})
  elif request.POST:
    if entity == 'attribute':
      pass
    elif entity == 'variable':
      pass
    else:
      return render_to_response('index.html', {'message' : 'No such entity'})
  
def split_path(path):
  """
  return the locale, by inspecting the urlpath (fed in the request)
  path examples:
  /hierarchy/variable.rank/
  """
  
  return path.split('/')[-2:]
               
@login_required
def display(request, path):
  if request.GET:
    (locale, child) = split_path(path)
    location = models.Collection(name=locale)
    if not location:
      # Path not found
      return render_to_response('index.html')
    # get the instances for the Collection
    instances = location.instances
    # need to group by variables
    grouped = {}
    for instance in instances:
      grouped.setdefault(instance.variable.key(), []).append(instance)
    # Sort the variables according to the rank
    for variable_list in grouped.values():
      variable_list.sort(key=lambda x: x.attribute.rank)
    # Ok we've grouped... now give me some links
    #variable = 
    if child:
      child_content = """<form name="attributes" action="update_attribute" method="post">"""
      # child specified
      for instance_attr in grouped.get(child):
        if instance_attr.attribute.has_key('references'):
          # handle the reference here to an additional var
          pass
        elif instance_attr.attribute.has_key('reference_to'):
          # Item with a codelists
          codelist_name = instance_attr.attribute.get('reference_to')
          # load the codelist here
          ct = CodedTerminology(name=codelist_name)
          if instance_attr.attribute.get(''):
            
            pass
        else:
          # bog standard element
          child_content += """<div class="question" id="%s_block">
            <div class="label" id="%s_label">%s</div>
            <div class="value" id="%s_value">
            <input type="text" name="%s">%s</input>
            </div>
            <div class="help" id="%s_help">%s</div>
            </div>""" % (instance.key(), 
                         instance.key(),
                         instance.attribute.label,
                         instance.key(),
                         instance.attribute.name,
                         instance.value,
                         instance.key(),
                         instance.attribute.guidelines)
        
      child_content += """<input type="button" value="Submit"/>"""
      child_content += """</form>"""
      
    else:
      child_content = ""
    for vble in sorted(instances, key=lambda x: x.variable.rank):
      list_content = ""
      if child:
        if vble.key() == child:
          list_content += """<a class="current" href="/%s">%s</a>""" % (vble.key(), vble.variable.name)
        else:
          list_content += """<a href="/%s">%s</a>""" % (vble.key(), vble.variable.name)
      else:
        list_content += """<a href="/%s">%s</a>""" % (vble.key(), vble.variable.name)
    
#    instances = models.Instances.all().filter(parent=location)
#    instances.order("")
  else:
    pass

def create_child_collection(request):
  """
  Create a child collection:
  1. Take the current - assuming it's a template
  2. Capture General Attributes (Pop-up)
  3. Iterate over current variables 
  4. Create an instance reference
  5. If it's set to inherit, copy the value from the parent
  """
  try: 
    parent_locale = db.Model()
  except:
    pass
  name = request.get('Name')
  if request.get('Template') == 'Yes':
    # create a Template Collection
    name = request.get('Name')
  else:
    # create a Normal Collection
    name = request.get('Name')
    pass
  
